<?php
//******************************************************************
class sql {
	public $resource = null;
	public $query = "";
	public $queryType = null;
	public $affectedRows = null;
	public $selectedNumRows = null;
	public $totalRowsCount = null;
	public $lastInsertId = null;
	public $history = array();

	public function __construct() {
		if (!@mysql_pconnect (DB_HOST,DB_USER,DB_PASSWORD))
			throw new Exception("mySQL connect error. Please, try again later.");
		mysql_select_db (DB_NAME);
		mysql_query("SET CHARACTER SET utf8");
	}

	public function nulling() {
		$this->resource = null;
		$this->query = "";
		$this->queryType = null;
		$this->affectedRows = null;
		$this->selectedNumRows = null;
		$this->totalRowsCount = null;
		$this->lastInsertId = null;
	}

	private function parseQuery($query, $params) {
		if (is_array($params) && !empty($params)) {
			$params = array_map(array(&$this, "e"), $params);
			$query = vsprintf($query, $params);
		}

		$this->query = $query;
		if (preg_match("/^select\s+/is", $query)) {
			$this->queryType = "SELECT";
			$this->query = preg_replace("/^(select)(\s+)/is", "$1 SQL_CALC_FOUND_ROWS$2", $this->query);
		} elseif (preg_match("/^insert\s+/is", $query) OR preg_match("/^replace\s+/is", $query)) {
			$this->queryType = "INSERT";
		} elseif (preg_match("/^update\s+/is", $query)) {
			$this->queryType = "UPDATE";
		} elseif (preg_match("/^delete\s+/is", $query)) {
			$this->queryType = "DELETE";
		} else {
			$this->queryType = "OTHER";
		}
	}

	public function q($query) {
		if (SHOW_DEBUG_INFO) {
			$q_start_time = microtime(true);
		}

		$this->nulling();

		$args = func_get_args();
		array_shift($args);
		$this->parseQuery($query, $args);

		if ($this->resource = mysql_query($this->query)) {
			if ($this->queryType == "SELECT") {
				$this->selectedNumRows = mysql_num_rows($this->resource);
				$this->totalRowsCount = mysql_result(mysql_query("SELECT FOUND_ROWS()"),0);
				$return = $this->selectedNumRows;
			} elseif (in_array($this->queryType, array("INSERT", "UPDATE", "DELETE"))) {
				$this->lastInsertId = mysql_insert_id();
				$this->affectedRows = mysql_affected_rows();
				$return = $this->affectedRows;
			} else {
				$return = true;
			}
		} else {
			if (SHOW_DEBUG_INFO) {
				$this->history[] = array(
					'time' => 0,
					'query' => $this->query,
					'error' => mysql_error()
				);
			}
			throw new Exception("DB error: ".mysql_error());
		}
		
		if (SHOW_DEBUG_INFO) {
			$this->history[] = array(
				'time' => (microtime(true) - $q_start_time),
				'query' => $this->query
			);
		}
		
		return $return;
	}

	public function e($string) {
		return mysql_real_escape_string($string);
	}

	public function getValueFromDB($query) {
		$args = func_get_args();
		if (call_user_func_array(array(&$this, "q"), $args) && $this->queryType=="SELECT") {
			return mysql_result($this->resource, 0);
		} else {
			return null;
		}
	}

	public function getRowFromDB($query) {
		$args = func_get_args();
		if (call_user_func_array(array(&$this, "q"), $args) && $this->queryType=="SELECT") {
			return mysql_fetch_assoc($this->resource);
		} else {
			return null;
		}
	}

	public function getAssocFromDB($query) {
		$args = func_get_args();
		if (call_user_func_array(array(&$this, "q"), $args) && $this->queryType=="SELECT") {
			while ($row = mysql_fetch_row($this->resource)) {
				$out[$row[0]] = $row[1];
			}
			return $out;
		} else {
			return array();
		}
	}

	public function getArrayFromDB($query) {
		$args = func_get_args();
		if (call_user_func_array(array(&$this, "q"), $args) && $this->queryType=="SELECT") {
			while ($row = mysql_fetch_assoc($this->resource)) {
				$out[] = $row;
			}
			return $out;
		} else {
			return array();
		}
	}

	public function getFields() {
		for ($i=0; $i<mysql_num_fields($this->resource); $i++)
			$fields[] = mysql_field_name($this->resource, $i);
		return $fields;
	}

	public function updateTable($tableName, $values, $keyName, $keyValue=null) {
		$sql = "UPDATE `".$tableName."` SET ";
		foreach ($values as $k => $v) {
			if (get_class($v) == "sqlFunction") {
				$sql .= "`".$k."`=".(string)$v.", ";
			} else {
				$sql .= "`".$k."`='".$this->e($v)."', ";
			}
		}
		$sql = substr($sql, 0, -2);
		
		if (is_array($keyName) and $keyValue === null) {
			$keys = $keyName;
		} else {
			$keys[$keyName] = $keyValue;
		}

		$sql .= " WHERE ";
		foreach ($keys as $k => $v) {
			if (get_class($v) == "sqlFunction") {
				$sql .= "`".$k."`=".(string)$v." AND ";
			} else {
				$sql .= "`".$k."`='".$this->e($v)."' AND ";
			}
		}
		$sql = substr($sql, 0, -4);

		$this->q($sql);
	}
	
	public function deleteFromTable($tableName, $keyName, $keyValue=null) {
		if (is_array($keyName) and $keyValue === null) {
			$keys = $keyName;
		} else {
			$keys[$keyName] = $keyValue;
		}
		
		$sql = "DELETE FROM `".$tableName."` WHERE ";
		foreach ($keys as $k => $v) {
			if (get_class($v) == "sqlFunction") {
				$sql .= "`".$k."`=".(string)$v." AND ";
			} else {
				$sql .= "`".$k."`='".$this->e($v)."' AND ";
			}
		}
		$sql = substr($sql, 0, -4);
		
		$this->q($sql);
	}

	public function insertIntoTable($tableName, $values, $replace=false) {
		foreach ($values as $k => $v) {
			if (get_class($v) == "sqlFunction") {
				$values[$k] = (string)$v;
			} else {
				$values[$k] = "'".$this->e($v)."'";
			}
		}
		$operator = ($replace)?'REPLACE':'INSERT';
		$sql = $operator." INTO `".$tableName."` (`".implode("`, `", array_keys($values))."`) VALUES (".implode(", ",$values).")";
		$this->q($sql);
	}

	public function getLimitSql($currentPage=1, $rowsPerPage=DEFAULT_ROWS_PER_PAGE) {
		$currentPage = (is_natural($currentPage) && $currentPage>0)?$currentPage:1;
		return " LIMIT ".($currentPage*$rowsPerPage-$rowsPerPage).", ".$rowsPerPage;
	}
}
//******************************************************************
class sqlFunction {
	function __construct($function) {
		$args = func_get_args();
		if (count($args)>1) {
			array_shift($args);
			$args = array_map(array("sql", "e"), $args);
			$function = vsprintf($function, $args);
		}
		$this->function = $function;
	}
	
	function __toString() {
		return $this->function;
	}
}
//******************************************************************
?>